Adaptive Runge-Kutta Method#

강좌: 수치해석

Adaptive Runge Kutta Method#

  • 2개의 정확도를 갖는 Runge Kutta 기법을 비교해서 상대 오차를 계산함

    • \(\tilde{y}_{n+1}\) 는 더 정확한 기법

    • \(y_{n}\) 의 오차 : \(Error \approx | y_{n+1} - \tilde{y}_{n+1} |\)

  • 시간 간격 \(h\) 조절

    • \(y_{n}\) LTE는 \(Error = O(h^{p+1})\) 이다.

    • \(y_{n}\) LTE를 \(\epsilon\) 까지 줄이려면 \(h_{opt} = h (\frac{\epsilon}{Error})^{1/(p+1)}\)

      • \(\epsilon = O(h_{opt}^{p+1})\) 이다.

Explicit Euler and Heun’s method#

Explicit Euler 기법의 시간 간격을 조절하기 위해서 고차 기법으로 2차 Runge-Kutta 기법중 하나인 Heun’s 기법을 사용하자.

  • Heun’s 기법을 구하는 과정에서 Explicit Euler 기법이 첫번째 Stage에서 바로 계산이 된다.

  • Extended butcher tableau

    \[\begin{split} \begin{array}{c|cc} 0 & 0 & \\ 1 & 1 & 0 \\ \hline & 1/2 & 1/2 \\ & 1 & 0 \end{array} \end{split}\]
  • 시간간격은 다음과 같이 조절한다.

    • \(\tilde{y}_{n+1}\): Huen’s 기법

    • \(y_{n+1}\): Euler Explicit 기법

    • \(LTE \approx | y_{n+1} - \tilde{y}_{n+1} | = O(h^2)\)

    • 목표 LTE: \(\epsilon = atol + rtol \times |y|\)

    • 최적 시간 간격: \(h_{opt} = s_{fac} h (\frac{\epsilon}{Error})^{1/2}\)

      • \(s_{fac} = 0.9\)

Embeded Runge Kutta Method#

  • 기존 Stage에 일부 Stage를 추가해서 정확도가 다른 Runge Kutta Approximation을 동시에 계산함

  • Runge-Kutta-Fehlberg method, DOPRI method 등이 존재함

  • 여러 기법들이 존재함

%matplotlib inline
from matplotlib import pyplot as plt

import numpy as np

plt.style.use('ggplot')
plt.rcParams['figure.dpi'] = 150
# 주요 상수
m, c, g = 68.1, 12.5, 9.81

# 우변 함수 작성
def f(t, v):
    return g - c/m*v
# 엄밀해 계산 함수
def exact(t):
    return g*m/c*(1-np.exp(-(c/m)*t))
# 시간간격
h = 2.0

# 최종 시간
te = 30

# Tolerance
atol, rtol = 1e-3, 1e-3
sfac = 0.9

# 초기조건
v0 = 0

# 계신 시간 간격
t = []
y = []

t.append(0)
y.append(v0)
ti, yi = 0, v0

while ti < te:
    # Explicit Euler
    yn = yi + h*f(ti, yi)

    # Heun's method
    yp = yi + 0.5*h*(f(ti, yi) + f(ti, yn))

    # error
    err = yn - yp

    # tolerance
    tol = atol + rtol*np.maximum(abs(yn), abs(yi))
    en = np.linalg.norm(err/tol)

    if en < 1.0:
        yi = yn
        ti += h
        y.append(yi)
        t.append(ti)

    ratio = sfac*en**(-0.5)
    h *= ratio
    
t = np.array(t)
y = np.array(y)
# Plot Exact solution and Numerical solution
plt.plot(t, exact(t))
plt.plot(t, y, marker='x',)

# 그래프 선 이름
plt.legend(['Exact', 'Adpative'])

# x,y 축 이름
plt.xlabel('Time (s)')
plt.ylabel('Velocity (m/s)')

# 그래프 이름
plt.title('Velocity of Paratrooper')
Text(0.5, 1.0, 'Velocity of Paratrooper')
../_images/e3b9b688a7d98615ec94954a4c48a400ef7a4a7c29ae1e90b12d0132d27f8000.png